//! 客户端侧交易订单DTO
//!

use crate::DataTransferObject;
use pyo3::prelude::*;
use serde::{Deserialize, Serialize};
use std::hash::Hasher;

#[pyclass]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum Direction {
    Long,  // 多头
    Short, // 空头
}

#[pyclass]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum PositionEffect {
    Open,   // 开仓
    Close,  // 平仓
}

#[pyclass]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum OrderStatus {
    Unfilled,        // 未成交
    PartiallyFilled, // 部分成交
    Filled,          // 完全成交
    Canceled,        // 已撤单
    Rejected,        // 拒绝
    Pending,         // 待处理
}

/// 订单
#[pyclass]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Order {
    #[pyo3(get)]
    pub id: Option<u64>, // 订单ID, 服务侧自动生成
    #[pyo3(get, set)]
    pub symbol: String,                  // 品种
    #[pyo3(get, set)]
    pub direction: Direction,            // 方向
    #[pyo3(get, set)]
    pub position_effect: PositionEffect, // 指令
    #[pyo3(get, set)]
    pub price: Option<f64>,              // 价格, None表示市价单
    #[pyo3(get, set)]
    pub quantity: u64,                   // 数量
    #[pyo3(get)]
    pub status: OrderStatus,             // 订单状态
    #[pyo3(get)]
    pub timestamp_us: Option<u64>,       // 服务器接收时间戳(microseconds)
}

impl DataTransferObject for Order {
    // Derive
}

#[pymethods]
impl Order {
    #[new]
    #[pyo3(signature = (symbol, direction, position_effect, quantity, price = None))]
    pub fn new(
        symbol: String,
        direction: Direction,
        position_effect: PositionEffect,
        quantity: u64,
        price: Option<f64>,
    ) -> Self {
        Order {
            id: None,
            symbol,
            direction,
            position_effect,
            price,
            quantity,
            status: OrderStatus::Pending,
            timestamp_us: None, // 时间戳由服务端生成
        }
    }

    #[pyo3(signature = (id))]
    pub fn set_id(&mut self, id: u64) {
        self.id = Some(id);
    }

    fn __repr__(&self) -> String {
        format!("Order(id={:?}, symbol={}, direction={:?}, position_effect={:?}, quantity={}, price={:?}, status={:?}, timestamp_us={:?})",
                self.id, self.symbol, self.direction, self.position_effect, self.quantity, self.price, self.status, self.timestamp_us)
    }

    fn __eq__(&self, other: PyRef<'_, Self>) -> bool {
        *self == *other
    }

    fn __hash__(&self) -> u64 {
        let mut hasher = std::collections::hash_map::DefaultHasher::new();
        if let Ok(serialized) = bincode::serialize(self) {
            hasher.write(&serialized);
        }
        hasher.finish()
    }
}

#[pyclass]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum Operation {
    Check,  // 查询订单信息
    Cancel, // 撤销订单
}

#[pyclass]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct OrderOperation {
    #[pyo3(get, set)]
    pub id: u64, // 订单ID
    #[pyo3(get, set)]
    pub operation: Operation,
}

impl DataTransferObject for OrderOperation {
    // Derive
}

#[pymethods]
impl OrderOperation {
    #[new]
    pub fn new(id: u64, operation: Operation) -> Self {
        OrderOperation { id, operation }
    }

    fn __repr__(&self) -> String {
        format!("OrderOperation(id={}, operation={:?})", self.id, self.operation)
    }
}
